{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 注意！请根据提示操作！\n",
    "\n",
    "如果当页面加载完成，你还是看到了这条提示\n",
    "\n",
    "那么你的notebook并未被信任，导致代码无法正常运行\n",
    "\n",
    "点击右上角的`不可信`，将本notebook列入可信列表，即可正常运行。\n",
    "\n",
    "![可信按钮](./mgr/trust.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 函数\n",
    "\n",
    "还记得数学里的函数么？这里随便写一个：\n",
    "\n",
    "$$y = f(x)$$\n",
    "\n",
    "在数学中，x是自变量，y是因变量，而f是函数的名字。\n",
    "\n",
    "而在编程中，x是参数，y是返回值，而f，还是函数的名字。\n",
    "\n",
    "例如数学中：\n",
    "\n",
    "$$f(x) = x ^ 2$$\n",
    "\n",
    "求y = f(3)的值，答案应该是9。\n",
    "\n",
    "那么编程中："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def f(x):  # def为定义函数的关键字，f为函数名，x为传入的参数\n",
    "    return x ** 2  # 返回x的平方的值给调用的地方\n",
    "\n",
    "y = f(3)  # y会获取到f函数运行后的返回值\n",
    "print(y)  # 输出y"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "利用函数，可以将某些需要重复使用的功能进行封装，方便调用和逻辑理解。例如[008T3-【测试】判断素数](008T3-【测试】判断素数.ipynb)中的判断素数算法，相对而言有点复杂："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = int(input())\n",
    "flag = True\n",
    "for i in range(2, int(x ** 0.5)):\n",
    "    if x % i == 0:\n",
    "        flag = False\n",
    "if flag:\n",
    "    print(1)  # 是素数\n",
    "else:\n",
    "    print(0)  # 不是素数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "此时假如需要你判断一个列表l中的数哪些是素数，代码可能会修改较多："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "l = [2, 5, 12, 54, 765, 76875, 686, 345]  # 一系列的数，判断是不是素数\n",
    "for x in l:\n",
    "    flag = True\n",
    "    for i in range(2, int(x ** 0.5)):\n",
    "        if x % i == 0:\n",
    "            flag = False\n",
    "    if flag:\n",
    "        print(str(x) + '是素数')  # 是素数\n",
    "    else:\n",
    "        print(str(x) + '不是素数')  # 不是素数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "遇到这种某项功能需要反复调用的情况，我们就可以将其写成函数，方便之后直接使用。例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "def is_prime(x):\n",
    "    for i in range(2, int(x ** 0.5)):\n",
    "        if x % i == 0:\n",
    "            return False  # 此处x可以被i整除，所以x必定不是素数，return返回False，return运行后，函数后面即便还有没运行完的代码，也将不会运行\n",
    "    return True\n",
    "\n",
    "x = int(input())\n",
    "if is_prime(x):  # 返回值是True和False，可以直接放到if中进行判断\n",
    "    print(1)  # 是素数\n",
    "else:\n",
    "    print(0)  # 不是素数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这样当你需要判断一系列的数是否是素数时，调用也很方便了："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义函数，定义结束后并不会运行\n",
    "def is_prime(x):\n",
    "    for i in range(2, int(x ** 0.5)):\n",
    "        if x % i == 0:\n",
    "            return False  # 此处x可以被i整除，所以x必定不是素数，return返回False，return运行后，函数后面即便还有没运行完的代码，也将不会运行\n",
    "    return True\n",
    "\n",
    "l = [2, 5, 12, 54, 765, 76875, 686, 345]  # 一系列的数，判断是不是素数\n",
    "for x in l:\n",
    "    # 被调用时函数才会运行\n",
    "    if is_prime(x):\n",
    "        print(str(x) + '是素数')  # 是素数\n",
    "    else:\n",
    "        print(str(x) + '不是素数')  # 不是素数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 函数的参数\n",
    "\n",
    "函数可以传入多个参数，例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def zhengchu(x, y):\n",
    "    if x % y == 0:  # 这里有办法用更加简单的方式来处理，可以自己思考下\n",
    "        return True\n",
    "    else:\n",
    "        return False\n",
    "\n",
    "print(zhengchu(10, 5))  # 看看10能否被5整除\n",
    "print(zhengchu(y=12, x=24))  # 我们可以用这种方法指定某个值传给某个参数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 函数的返回值\n",
    "\n",
    "函数也可以获取多种不同类型的返回值，包括可以获取多个返回值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_big_two(x, y, z):  # 获取三个参数中较大的两个参数\n",
    "    if min(x, y, z) == x:  # min可以获取参数中的最小值\n",
    "        return y, z\n",
    "    elif min(x, y, z) == y:\n",
    "        return x, z\n",
    "    else:\n",
    "        return x, y\n",
    "\n",
    "a, b = get_big_two(10, 52, 32)\n",
    "print(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 一些补充\n",
    "\n",
    "不知道你有没有发现，print()其实就是一个函数，它可以获取多个不同的参数，然后将他们输出到屏幕上。print没有返回值。一个函数允许没有返回值。同样上述代码中的min()其实也是一个函数，还有input()也是函数。这些函数不需要我们去定义，直接就能用，原因是在Python官方的模块中就帮我们定义好了，我们不需要再去定义他们。这种就叫做内置函数。\n",
    "\n",
    "而函数的返回值，可以赋值给某个变量，也可以直接去使用，例如上述的print(zhengchu(10, 5))，直接把zhengchu函数的返回值给了print作为参数，print将其输出。\n",
    "\n",
    "\n",
    "## 合法函数名\n",
    "\n",
    "函数名的规范和变量名一致，可以查看[变量名的规范](004-变量.ipynb#命名规范)。\n",
    "\n",
    "函数名与变量名同享一个命名空间，所以函数名和变量名不能重复，否则会有问题。\n",
    "\n",
    "例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = 1\n",
    "def a(x):\n",
    "    return x ** 2\n",
    "print(a(3))  # 会输出3的平方\n",
    "print(a)  # 此时不会输出1，因为a的值已经被重定义成函数名了，此时会输出函数在内存中的位置。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "其实到后来你会发现，函数名就是一种特殊的变量名。这个会在后续的函数式编程中具体讲述。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<hr>\n",
       "<link rel=\"stylesheet\" href=\"//cdn.bootcss.com/mdui/0.4.3/css/mdui.min.css\">\n",
       "<script src=\"./mgr/submit.js\"></script>\n",
       "<script src=\"./mgr/hide.js\"></script>\n",
       "<div class=\"mdui-container-fluid\">\n",
       "    <div class=\"mdui-col-xs-3\">\n",
       "        <button class=\"mdui-btn mdui-btn-raised mdui-ripple mdui-color-blue-grey-500\" onclick=\"next_page(-1)\">上一章</button>\n",
       "    </div>\n",
       "    <div class=\"mdui-col-xs-3\">\n",
       "        <button class=\"mdui-btn mdui-btn-raised mdui-ripple mdui-color-blue-grey-700\" onclick=\"window.open('/tree')\">目录</button>\n",
       "    </div>\n",
       "    <div class=\"mdui-col-xs-3\">\n",
       "        <button class=\"mdui-btn mdui-btn-raised mdui-ripple mdui-color-blue-grey-900\" onclick=\"next_page(1)\">下一章</button>\n",
       "    </div>\n",
       "</div>\n",
       "<div id=\"html_output\">\n",
       "</div>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%html\n",
    "<hr>\n",
    "<link rel=\"stylesheet\" href=\"//cdn.bootcss.com/mdui/0.4.3/css/mdui.min.css\">\n",
    "<script src=\"./mgr/submit.js\"></script>\n",
    "<script src=\"./mgr/hide.js\"></script>\n",
    "<div class=\"mdui-container-fluid\">\n",
    "    <div class=\"mdui-col-xs-3\">\n",
    "        <button class=\"mdui-btn mdui-btn-raised mdui-ripple mdui-color-blue-grey-500\" onclick=\"next_page(-1)\">上一章</button>\n",
    "    </div>\n",
    "    <div class=\"mdui-col-xs-3\">\n",
    "        <button class=\"mdui-btn mdui-btn-raised mdui-ripple mdui-color-blue-grey-700\" onclick=\"window.open('/tree')\">目录</button>\n",
    "    </div>\n",
    "    <div class=\"mdui-col-xs-3\">\n",
    "        <button class=\"mdui-btn mdui-btn-raised mdui-ripple mdui-color-blue-grey-900\" onclick=\"next_page(1)\">下一章</button>\n",
    "    </div>\n",
    "</div>\n",
    "<div id=\"html_output\">\n",
    "</div>"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
